-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[RISCV] Sink NOT to be fold into ANDN/ORN/XNOR/VANDN #131632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-backend-risc-v Author: Piotr Fusik (pfusik) ChangesUndoes a negation being hoisted out of a loop, so that it can be fold Implements #108840 on RISC-V Patch is 50.78 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131632.diff 4 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
index 11a658758a9cb..1060093043278 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
@@ -2779,6 +2779,39 @@ bool RISCVTTIImpl::isProfitableToSinkOperands(
Instruction *I, SmallVectorImpl<Use *> &Ops) const {
using namespace llvm::PatternMatch;
+ if (I->isBitwiseLogicOp()) {
+ if (!I->getType()->isVectorTy()) {
+ if (ST->hasStdExtZbb() || ST->hasStdExtZbkb()) {
+ for (auto &Op : I->operands()) {
+ // (and/or/xor X, (not Y)) -> (andn/orn/xnor X, Y)
+ if (match(Op.get(), m_Not(m_Value()))) {
+ Ops.push_back(&Op);
+ return true;
+ }
+ }
+ }
+ } else if (I->getOpcode() == Instruction::And && ST->hasStdExtZvkb()) {
+ for (auto &Op : I->operands()) {
+ // (and X, (not Y)) -> (vandn.vv X, Y)
+ if (match(Op.get(), m_Not(m_Value()))) {
+ Ops.push_back(&Op);
+ return true;
+ }
+ // (and X, (splat (not Y))) -> (vandn.vx X, Y)
+ if (match(Op.get(), m_Shuffle(m_InsertElt(m_Value(), m_Not(m_Value()),
+ m_ZeroInt()),
+ m_Value(), m_ZeroMask()))) {
+ Use &InsertElt = cast<Instruction>(Op)->getOperandUse(0);
+ Use &Not = cast<Instruction>(InsertElt)->getOperandUse(1);
+ Ops.push_back(&Not);
+ Ops.push_back(&InsertElt);
+ Ops.push_back(&Op);
+ return true;
+ }
+ }
+ }
+ }
+
if (!I->getType()->isVectorTy() || !ST->hasVInstructions())
return false;
diff --git a/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
index b6344f88cddaa..88bb19f499ab5 100644
--- a/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
@@ -438,3 +438,357 @@ define i1 @andn_snez_i64(i64 %a, i64 %b) nounwind {
%cmpeq = icmp ne i64 %and, %b
ret i1 %cmpeq
}
+
+define i32 @and_hoisted_not_i32(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV32I-LABEL: and_hoisted_not_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a2, .LBB24_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: and a0, a1, a0
+; RV32I-NEXT: .LBB24_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: and_hoisted_not_i32:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a2, .LBB24_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: andn a0, a0, a1
+; RV32ZBB-ZBKB-NEXT: .LBB24_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i32 %a, %x
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i32 @and_hoisted_not_i32_swapped(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV32I-LABEL: and_hoisted_not_i32_swapped:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a2, .LBB25_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: and a0, a0, a1
+; RV32I-NEXT: .LBB25_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: and_hoisted_not_i32_swapped:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a2, .LBB25_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: andn a0, a0, a1
+; RV32ZBB-ZBKB-NEXT: .LBB25_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i32 %x, %a
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i64 @and_hoisted_not_i64(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV32I-LABEL: and_hoisted_not_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a4, .LBB26_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a3, a3
+; RV32I-NEXT: not a2, a2
+; RV32I-NEXT: and a0, a2, a0
+; RV32I-NEXT: and a1, a3, a1
+; RV32I-NEXT: .LBB26_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: and_hoisted_not_i64:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a4, .LBB26_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: andn a0, a0, a2
+; RV32ZBB-ZBKB-NEXT: andn a1, a1, a3
+; RV32ZBB-ZBKB-NEXT: .LBB26_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i64 %a, %x
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i64 @and_hoisted_not_i64_swapped(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV32I-LABEL: and_hoisted_not_i64_swapped:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a4, .LBB27_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a3, a3
+; RV32I-NEXT: not a2, a2
+; RV32I-NEXT: and a0, a0, a2
+; RV32I-NEXT: and a1, a1, a3
+; RV32I-NEXT: .LBB27_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: and_hoisted_not_i64_swapped:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a4, .LBB27_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: andn a0, a0, a2
+; RV32ZBB-ZBKB-NEXT: andn a1, a1, a3
+; RV32ZBB-ZBKB-NEXT: .LBB27_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i64 %x, %a
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i32 @or_hoisted_not_i32(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV32I-LABEL: or_hoisted_not_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a2, .LBB28_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: or a0, a1, a0
+; RV32I-NEXT: .LBB28_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: or_hoisted_not_i32:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a2, .LBB28_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: orn a0, a0, a1
+; RV32ZBB-ZBKB-NEXT: .LBB28_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i32 %a, %x
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i32 @or_hoisted_not_i32_swapped(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV32I-LABEL: or_hoisted_not_i32_swapped:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a2, .LBB29_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: or a0, a0, a1
+; RV32I-NEXT: .LBB29_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: or_hoisted_not_i32_swapped:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a2, .LBB29_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: orn a0, a0, a1
+; RV32ZBB-ZBKB-NEXT: .LBB29_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i32 %x, %a
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i64 @or_hoisted_not_i64(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV32I-LABEL: or_hoisted_not_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a4, .LBB30_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a3, a3
+; RV32I-NEXT: not a2, a2
+; RV32I-NEXT: or a0, a2, a0
+; RV32I-NEXT: or a1, a3, a1
+; RV32I-NEXT: .LBB30_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: or_hoisted_not_i64:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a4, .LBB30_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: orn a0, a0, a2
+; RV32ZBB-ZBKB-NEXT: orn a1, a1, a3
+; RV32ZBB-ZBKB-NEXT: .LBB30_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i64 %a, %x
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i64 @or_hoisted_not_i64_swapped(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV32I-LABEL: or_hoisted_not_i64_swapped:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a4, .LBB31_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a3, a3
+; RV32I-NEXT: not a2, a2
+; RV32I-NEXT: or a0, a0, a2
+; RV32I-NEXT: or a1, a1, a3
+; RV32I-NEXT: .LBB31_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: or_hoisted_not_i64_swapped:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a4, .LBB31_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: orn a0, a0, a2
+; RV32ZBB-ZBKB-NEXT: orn a1, a1, a3
+; RV32ZBB-ZBKB-NEXT: .LBB31_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i64 %x, %a
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i32 @xor_hoisted_not_i32(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV32I-LABEL: xor_hoisted_not_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a2, .LBB32_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: xor a0, a1, a0
+; RV32I-NEXT: .LBB32_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: xor_hoisted_not_i32:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a2, .LBB32_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: xnor a0, a1, a0
+; RV32ZBB-ZBKB-NEXT: .LBB32_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = xor i32 %a, %x
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i32 @xor_hoisted_not_i32_swapped(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV32I-LABEL: xor_hoisted_not_i32_swapped:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a2, .LBB33_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a1, a1
+; RV32I-NEXT: xor a0, a0, a1
+; RV32I-NEXT: .LBB33_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: xor_hoisted_not_i32_swapped:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a2, .LBB33_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: xnor a0, a1, a0
+; RV32ZBB-ZBKB-NEXT: .LBB33_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = xor i32 %x, %a
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i64 @xor_hoisted_not_i64(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV32I-LABEL: xor_hoisted_not_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a4, .LBB34_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a3, a3
+; RV32I-NEXT: not a2, a2
+; RV32I-NEXT: xor a0, a2, a0
+; RV32I-NEXT: xor a1, a3, a1
+; RV32I-NEXT: .LBB34_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: xor_hoisted_not_i64:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a4, .LBB34_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: xnor a0, a2, a0
+; RV32ZBB-ZBKB-NEXT: xnor a1, a3, a1
+; RV32ZBB-ZBKB-NEXT: .LBB34_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = xor i64 %a, %x
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i64 @xor_hoisted_not_i64_swapped(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV32I-LABEL: xor_hoisted_not_i64_swapped:
+; RV32I: # %bb.0:
+; RV32I-NEXT: beqz a4, .LBB35_2
+; RV32I-NEXT: # %bb.1: # %mask
+; RV32I-NEXT: not a3, a3
+; RV32I-NEXT: not a2, a2
+; RV32I-NEXT: xor a0, a0, a2
+; RV32I-NEXT: xor a1, a1, a3
+; RV32I-NEXT: .LBB35_2: # %identity
+; RV32I-NEXT: ret
+;
+; RV32ZBB-ZBKB-LABEL: xor_hoisted_not_i64_swapped:
+; RV32ZBB-ZBKB: # %bb.0:
+; RV32ZBB-ZBKB-NEXT: beqz a4, .LBB35_2
+; RV32ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV32ZBB-ZBKB-NEXT: xnor a0, a2, a0
+; RV32ZBB-ZBKB-NEXT: xnor a1, a3, a1
+; RV32ZBB-ZBKB-NEXT: .LBB35_2: # %identity
+; RV32ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = xor i64 %x, %a
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
index bf077364c9c7a..4ca637b788a45 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
@@ -554,3 +554,339 @@ define i1 @andn_snez_i64(i64 %a, i64 %b) nounwind {
%cmpeq = icmp ne i64 %and, %b
ret i1 %cmpeq
}
+
+define i32 @and_hoisted_not_i32(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV64I-LABEL: and_hoisted_not_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB32_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: .LBB32_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: and_hoisted_not_i32:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB32_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: andn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB32_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i32 %a, %x
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i32 @and_hoisted_not_i32_swapped(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV64I-LABEL: and_hoisted_not_i32_swapped:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB33_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: .LBB33_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: and_hoisted_not_i32_swapped:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB33_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: andn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB33_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i32 %x, %a
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i64 @and_hoisted_not_i64(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV64I-LABEL: and_hoisted_not_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB34_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: and a0, a1, a0
+; RV64I-NEXT: .LBB34_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: and_hoisted_not_i64:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB34_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: andn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB34_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i64 %a, %x
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i64 @and_hoisted_not_i64_swapped(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV64I-LABEL: and_hoisted_not_i64_swapped:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB35_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: and a0, a0, a1
+; RV64I-NEXT: .LBB35_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: and_hoisted_not_i64_swapped:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB35_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: andn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB35_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = and i64 %x, %a
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i32 @or_hoisted_not_i32(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV64I-LABEL: or_hoisted_not_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB36_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: or a0, a1, a0
+; RV64I-NEXT: .LBB36_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: or_hoisted_not_i32:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB36_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: orn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB36_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i32 %a, %x
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i32 @or_hoisted_not_i32_swapped(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV64I-LABEL: or_hoisted_not_i32_swapped:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB37_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: or a0, a0, a1
+; RV64I-NEXT: .LBB37_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: or_hoisted_not_i32_swapped:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB37_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: orn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB37_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i32 %x, %a
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i64 @or_hoisted_not_i64(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV64I-LABEL: or_hoisted_not_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB38_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: or a0, a1, a0
+; RV64I-NEXT: .LBB38_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: or_hoisted_not_i64:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB38_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: orn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB38_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i64 %a, %x
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i64 @or_hoisted_not_i64_swapped(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV64I-LABEL: or_hoisted_not_i64_swapped:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB39_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: or a0, a0, a1
+; RV64I-NEXT: .LBB39_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: or_hoisted_not_i64_swapped:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB39_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: orn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT: .LBB39_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i64 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = or i64 %x, %a
+ ret i64 %masked
+
+identity:
+ ret i64 %x
+}
+
+define i32 @xor_hoisted_not_i32(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV64I-LABEL: xor_hoisted_not_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB40_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: xor a0, a1, a0
+; RV64I-NEXT: .LBB40_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: xor_hoisted_not_i32:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB40_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: xnor a0, a1, a0
+; RV64ZBB-ZBKB-NEXT: .LBB40_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = xor i32 %a, %x
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i32 @xor_hoisted_not_i32_swapped(i32 %x, i32 %m, i1 zeroext %cond) {
+; RV64I-LABEL: xor_hoisted_not_i32_swapped:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB41_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: xor a0, a0, a1
+; RV64I-NEXT: .LBB41_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: xor_hoisted_not_i32_swapped:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB41_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: xnor a0, a1, a0
+; RV64ZBB-ZBKB-NEXT: .LBB41_2: # %identity
+; RV64ZBB-ZBKB-NEXT: ret
+ %a = xor i32 %m, -1
+ br i1 %cond, label %mask, label %identity
+
+mask:
+ %masked = xor i32 %x, %a
+ ret i32 %masked
+
+identity:
+ ret i32 %x
+}
+
+define i64 @xor_hoisted_not_i64(i64 %x, i64 %m, i1 zeroext %cond) {
+; RV64I-LABEL: xor_hoisted_not_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beqz a2, .LBB42_2
+; RV64I-NEXT: # %bb.1: # %mask
+; RV64I-NEXT: not a1, a1
+; RV64I-NEXT: xor a0, a1, a0
+; RV64I-NEXT: .LBB42_2: # %identity
+; RV64I-NEXT: ret
+;
+; RV64ZBB-ZBKB-LABEL: xor_hoisted_not_i64:
+; RV64ZBB-ZBKB: # %bb.0:
+; RV64ZBB-ZBKB-NEXT: beqz a2, .LBB42_2
+; RV64ZBB-ZBKB-NEXT: # %bb.1: # %mask
+; RV64ZBB-ZBKB-NEXT: xnor a0, a1, a0
+; RV64ZBB-ZBKB-NEXT: .LBB42_2: # %identity
+; RV6...
[truncated]
|
|
|
||
| declare i64 @llvm.vscale.i64() | ||
|
|
||
| define void @vand_vx_loop_hoisted_not(ptr %a, i32 noundef signext %mask) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
void vand_vx_loop_hoisted_not(int *a, int mask) {
for (int i = 0; i < 256; i++)
a[i] &= ~mask;
}
lenary
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CodeGen changes here look good to me. I'm less familiar with how exactly the implementation should be written, but the implementation looks clear to me. Please wait another 24 hours in case there are other reviewers with stronger opinions than mine
topperc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Undoes a negation being hoisted out of a loop, so that it can be fold into an inverted bitwise operation in the loop. Implements llvm#108840 on RISC-V
|
Tests merged into main branch as 6ada38b. PR rebased. |
Undoes a negation being hoisted out of a loop, so that it can be fold
into an inverted bitwise operation in the loop.
Implements #108840 on RISC-V